{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Geodepy Tutorial: Time-Dependent Datum Transformations\n",
    "\n",
    "This tutorial demonstrates the use of GeodePy for transformations between time-dependent dynamic datums. We'll work through each of the steps required to tranform a coordinate in ITRF2005 at epoch 2000.0 to ITRF2014 at 2020.0 on the Australian Plate, then build a function containing these steps to simplify this process."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Start by importing the following Functions and Modules (datetime is used for the representation of epochs):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [],
   "source": [
    "from datetime import date\n",
    "from geodepy.constants import itrf14togda20, itrf14to05\n",
    "from geodepy.transform import *"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We'll define a point for transformation. For this exercise, we'll use a point called Bob which is in terms of ITRF2005 at epoch 2000.0 and is shown using a UTM projection. The parts below are (zone, easting, northing, ellipsoidal height):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [],
   "source": [
    "bob = (53, 386353.2371, 7381852.2967, 587.5814)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Part 1: Getting Things in the Right Format\n",
    "To convert between time-dependent datums, we need our coordinates to be in Cartesian (XYZ) format. To get Bob in this format, we start by converting the UTM part (zone, easting and northing) into Geographic (latitude and longitude) format:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(-23.67011015602, 133.88552163574)"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "lat, lon, psf, grid_conv = grid2geo(bob[0], bob[1], bob[2])\n",
    "lat, lon"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can now use Bob's Latitude, Longitude and Ellipsoidal Height to calculate Cartesian Coordinates for Bob. These are still in terms of ITRF2005 at epoch 2000.0:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(-4052042.792092285, 4212825.645301948, -2545098.3015855583)"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x, y, z = llh2xyz(lat, lon, bob[3])\n",
    "x, y, z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Part 2: Moving to the Reference Epoch\n",
    "Transformations between datums in GeodePy use Transformation Objects which are contained in the Constants module. These contain parameters used in Conformal (Helmert) 7 and 15 parameter transformations. To go between ITRF2005 and ITRF2014, we use `itrf14to05`, but because we're going the other way we use `-itrf14to05`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Transformation: From 'ITRF2005' to 'ITRF2014'\n",
       "Reference Epoch: datetime.date(2010, 1, 1)\n",
       "  tx: -0.0026m + -0.0003m/yr\n",
       "  ty: -0.001m + -0.0m/yr\n",
       "  tz: 0.0023m + 0.0001m/yr\n",
       "  sc: -0.00092ppm + -3e-05ppm/yr\n",
       "  rx: -0.0\" + -0.0\"/yr\n",
       "  ry: -0.0\" + -0.0\"/yr\n",
       "  rz: -0.0\" + -0.0\"/yr"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "-itrf14to05"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Before we can use this, we need to get our coordinates into the Reference Epoch of the transformation we plan to use (in this case, 2010.0 or the 1st Jan 2010). Because Bob is in Australia, we need to use the Australian Plate Motion Model to do this. It's parameters are in `itrf14togda20`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Transformation: From 'ITRF2014' to 'GDA2020'\n",
       "Reference Epoch: datetime.date(2020, 1, 1)\n",
       "  tx: 0m + 0m/yr\n",
       "  ty: 0m + 0m/yr\n",
       "  tz: 0m + 0m/yr\n",
       "  sc: 0ppm + 0ppm/yr\n",
       "  rx: 0\" + 0.00150379\"/yr\n",
       "  ry: 0\" + 0.00118346\"/yr\n",
       "  rz: 0\" + 0.00120716\"/yr"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "itrf14togda20"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It also has a reference epoch; for `itrf14togda20`, it's 2020.0. So to move coordinates from 2000.0 to 2010.0 (+10.0 years) using `itrf14togda20` we need to use `conform14` with a `to_epoch` 10.0 years past our reference epoch (2020.0 + 10.0 = 2030.0):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(-4052042.792092285, 4212825.645301948, -2545098.3015855583)"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x, y, z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(-4052042.3994570016, 4212825.69690139, -2545098.841287901)"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x2, y2, z2 = conform14(x, y, z, date(2030, 1, 1), itrf14togda20)\n",
    "x2, y2, z2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We now have Bob's Cartesian Coordinates in ITRF2005 at epoch 2010.0!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Part 3: The Transformation\n",
    "Now that we have Bob's coordinates in the reference epoch of `itrf14to05`, we can perform this transformation. Because we're not changing epochs in this part, we can use the `conform7` function which ignores the time-dependent parameters of our transformation:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(-4052042.3983291225, 4212825.692025591, -2545098.8366464106)"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x3, y3, z3 = conform7(x2, y2, z2, -itrf14to05)\n",
    "x3, y3, z3"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This gives us Bob's Cartesian Coordinates in ITRF2014 at epoch 2010.0.\n",
    "#### Part 4: Moving to the Final Epoch\n",
    "The final tranformation is moving Bob's epoch to it's final destination (2020.0) using `itrf14togda20`. As the period of movement (2010.0 to 2020.0) is the same (+10.0 years), we use the same `to_epoch` of 2030.0 as in Part 2:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(-4052042.0056938054, 4212825.743624971, -2545099.376348734)"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x4, y4, z4 = conform14(x3, y3, z3, date(2030, 1, 1), itrf14togda20)\n",
    "x4, y4, z4"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "These coordinates are now in terms of ITRF2014 at epoch 2020.0\n",
    "#### Part 5: Getting Things in their Original Format\n",
    "To bring everything back into the format we started, we'll step through the process in Part 1 in reverse. So we'll start by converting our Cartesian Coordinates to Geographic format:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(-23.670120761985057, 133.8855154120127, 587.5785029223189)"
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "lat_end, lon_end, ell_ht_end = xyz2llh(x4, y4, z4)\n",
    "lat_end, lon_end, ell_ht_end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we'll convert the latitude and longitude into UTM grid coordinates:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(53, 386352.6116, 7381851.1174)"
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "hem_end, zone_end, east_end, north_end, psf_end, grid_conv_end = geo2grid(lat_end, lon_end)\n",
    "zone_end, east_end, north_end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Combining this with our ellipsoidal height from above, we get the final coordinate:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(53, 386352.6116, 7381851.1174, 587.5785029223189)"
      ]
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "zone_end, east_end, north_end, ell_ht_end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can then compare the starting coordinate to the final coordinate and see the difference:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(53, 386352.6116, 7381851.1174, 587.5785029223189)"
      ]
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bob_end = (zone_end, east_end, north_end, ell_ht_end)\n",
    "bob_end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(53, 386353.2371, 7381852.2967, 587.5814)"
      ]
     },
     "execution_count": 69,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bob"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Part 6: Simplifying steps into a single function\n",
    "To wrap up this tutorial, we'll combine all of the steps above into a single function:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(53, 386352.6116, 7381851.1174, 587.5785029223189)"
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def bobtransform(zone, east, north, ell_ht):\n",
    "    lat, lon, psf, grid_conv = grid2geo(zone, east, north)\n",
    "    x, y, z = llh2xyz(lat, lon, ell_ht)\n",
    "    x2, y2, z2 = conform14(x, y, z, date(2030, 1, 1), itrf14togda20)\n",
    "    x3, y3, z3 = conform7(x2, y2, z2, -itrf14to05)\n",
    "    x4, y4, z4 = conform14(x3, y3, z3, date(2030, 1, 1), itrf14togda20)\n",
    "    lat_end, lon_end, ell_ht_end = xyz2llh(x4, y4, z4)\n",
    "    hem_end, zone_end, east_end, north_end, psf_end, grid_conv_end = geo2grid(lat_end, lon_end)\n",
    "    return zone_end, east_end, north_end, ell_ht_end\n",
    "\n",
    "newbob = bobtransform(bob[0], bob[1], bob[2], bob[3])\n",
    "newbob"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
